package cn.frontop.funswitch.config.apiFileter;

import cn.frontop.funswitch.common.CommonConstant;
import cn.frontop.funswitch.common.Result;
import cn.frontop.funswitch.config.web.ServiceContext;
import cn.frontop.funswitch.entity.ApiPathEntity;
import cn.frontop.funswitch.exception.FunSwitchException;
import cn.frontop.funswitch.service.ApiPathService;
import cn.frontop.funswitch.service.IndexConfigService;
import cn.frontop.funswitch.util.CommonUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Objects;

import static cn.frontop.funswitch.config.web.ServiceContext.REQUEST_ID;

/**
 * @author Yun
 */
@Slf4j
@Component
public class ApiServlet extends HttpServlet {

    @Autowired
    ApiPathService apiPathService;
    @Autowired
    IndexConfigService indexConfigService;

    /**
     * 拦截 post 请求 作为动态api接口输出 仅拦截 funSwitch.api.context
     *
     * @param req
     * @param resp
     * @throws IOException
     */
    @Override
    @SuppressWarnings({"rawtypes", "ConstantConditions"})
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        initRequestId();
        //获取请求路径
        String servletPath = req.getRequestURI();
        //切割获取末尾路由 /web/path ====> path
        servletPath = servletPath.substring(servletPath.lastIndexOf("/") + 1);
        // 获取ip
        String ip = req.getRemoteAddr();
        ApiPathEntity apiPathEntity = apiPathService.getBaseMapper().selectOne(new QueryWrapper<ApiPathEntity>().lambda().eq(ApiPathEntity::getApiPath, servletPath).eq(ApiPathEntity::isStatus, true));
        PrintWriter out = null;
        Result result = new Result();
        try {
            out = resp.getWriter();
            resp.setContentType("application/json;charset=UTF-8");
            resp.setCharacterEncoding("UTF-8");
            // 判断ip是否在黑白名单内
            ipFilter(apiPathEntity, ip);
            //获取api结果
            result = CommonUtil.process(apiPathEntity, req, indexConfigService);
            result.setRequestId(ServiceContext.getRequestId());
            resp.setStatus(result.getCode());
            out.append(JSONUtil.toJsonStr(result));
        } catch (Exception e) {
            result.setCode(Result.ResultEnum.ERROR.getRespCode());
            result.setRequestId(ServiceContext.getRequestId());
            result.setMessage(e.getMessage());
            out.append(JSONUtil.toJsonStr(result));
            log.error(e.toString(), e);
            throw e;
        } finally {
            if (out != null) {
                out.close();
            }
            clearRequestId();
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }


    /**
     * 黑白名单过滤器
     * 0.放行 1.黑名单2.白名单
     *
     * @param apiPathEntity 实体
     */
    private void ipFilter(ApiPathEntity apiPathEntity, String ip) {
        if (apiPathEntity.getRule().equals(CommonConstant.GREEN_LIGHT)) {
            return;
        }
        if (StrUtil.isNotEmpty(apiPathEntity.getList()) && !(JSONUtil.parseArray(apiPathEntity.getList()).isEmpty())) {
            JSONArray jsonArray = JSONUtil.parseArray(apiPathEntity.getList());
            boolean temp = jsonArray.contains(ip);
            if (apiPathEntity.getRule().equals(CommonConstant.BLACK_LIST) && temp || apiPathEntity.getRule().equals(CommonConstant.WHITE_LIST) && !temp) {
                throw new FunSwitchException("无权限,访问!");
            } else if (apiPathEntity.getRule() > CommonConstant.WHITE_LIST || apiPathEntity.getRule() < CommonConstant.GREEN_LIGHT) {
                throw new FunSwitchException("规则有误!!!");
            }
        }
    }

    /**
     * 匹配请求参数
     *
     * @param request
     * @param jsonArray
     * @return
     */
    @SuppressWarnings("SuspiciousMethodCalls")
    private JSONObject getParams(HttpServletRequest request, JSONArray jsonArray) {
        String contentType = request.getContentType();
        //必须是application/json请求
        if (contentType.equalsIgnoreCase(CommonConstant.APP_JSON)) {
            JSONObject jsonObject = new JSONObject();
            JSONObject httpJsonBody = CommonUtil.getHttpJsonBody(request);
            if (Objects.isNull(httpJsonBody)) {
                return new JSONObject();
            }
            for (int i = 0; i < jsonArray.size(); i++) {
                jsonObject.set(jsonArray.getStr(i), httpJsonBody.get(jsonArray.get(i)));
            }
            return jsonObject;
        } else {
            throw new RuntimeException("请求方式不规范!");
        }
    }

    /**
     * 初始化 请求ID
     */
    private void initRequestId(){
        String requestId = IdUtil.simpleUUID();
        MDC.put(ServiceContext.REQUEST_ID,requestId );
        ServiceContext.setRequestId(requestId);
    }

    /**
     * 删除请求ID
     */
    private void clearRequestId(){
        //销毁请求id
        ServiceContext.clearAll();
        MDC.clear();
    }


}
